use serde::{Deserialize, Serialize};
use uuid::Uuid;
use chrono::{DateTime, Utc};
use super::{policy::Policy, policy_db_model::Model};

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SignaturePolicy {
    pub policy_id: Uuid,
    pub policy_name: String,
    pub policy_description: String,
    pub policy_content: String,
    pub policy_version: i32,
    pub key_version: String,
    pub attester_type: Vec<String>,
    pub is_default: bool,
    pub user_id: String,
    pub update_time: DateTime<Utc>,
    pub create_time: DateTime<Utc>,
    pub signature: Vec<u8>,
    pub valid_code: i8,
    pub product_name: String,
    pub product_type: String,
    pub board_type: String,
}

impl SignaturePolicy {

    pub fn encode_to_bytes(&self) -> Vec<u8> {
        let mut bytes = Vec::new();
        
        bytes.extend_from_slice(self.policy_id.as_bytes().as_ref());
        bytes.extend_from_slice(self.policy_name.as_bytes());
        bytes.extend_from_slice(self.policy_description.as_bytes());
        bytes.extend_from_slice(self.policy_content.as_bytes());
        bytes.extend_from_slice(&self.policy_version.to_le_bytes());
        for attester in &self.attester_type {
            bytes.extend_from_slice(attester.as_bytes());
        }
        bytes.extend_from_slice(&[self.is_default as u8]);
        bytes.extend_from_slice(self.user_id.as_bytes());
        bytes.extend_from_slice(&self.update_time.timestamp().to_le_bytes());
        bytes.extend_from_slice(&self.create_time.timestamp().to_le_bytes());
        bytes.extend_from_slice(self.product_name.as_bytes());
        bytes.extend_from_slice(self.product_type.as_bytes());
        bytes.extend_from_slice(self.board_type.as_bytes());
        bytes.extend_from_slice(&[self.valid_code as u8]);
        bytes
    }
}

impl From<Model> for SignaturePolicy {
    fn from(model: Model) -> Self {
        let attester_type: Vec<String> = serde_json::from_value(model.attester_type)
            .unwrap_or_default();

        SignaturePolicy {
            policy_id: Uuid::parse_str(&model.policy_id).unwrap(),
            policy_name: model.policy_name,
            policy_description: model.policy_description,
            policy_content: model.policy_content,
            policy_version: model.policy_version,
            key_version: model.key_version,
            attester_type,
            is_default: model.is_default,
            user_id: model.user_id,
            update_time: model.update_time,
            create_time: model.create_time,
            signature: model.signature,
            valid_code: model.valid_code,
            product_name: model.product_name,
            product_type: model.product_type,
            board_type: model.board_type,
        }
    }
}

impl From<SignaturePolicy> for Policy {
    fn from(signature_policy: SignaturePolicy) -> Self {
        Policy {
            id: signature_policy.policy_id,
            name: signature_policy.policy_name,
            description: signature_policy.policy_description,
            content: signature_policy.policy_content,
            attester_type: signature_policy.attester_type,
            is_default: signature_policy.is_default,
            version: signature_policy.policy_version as u32,
            update_time: signature_policy.update_time.timestamp() as u64,
            valid_code: signature_policy.valid_code as i8,
        }
    }
}
